home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / feedback.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-04  |  10.0 KB  |  418 lines

  1. /* $Id: feedback.c,v 3.3 1998/02/21 01:32:49 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: feedback.c,v $
  26.  * Revision 3.3  1998/02/21 01:32:49  brianp
  27.  * fixed bug in gl_InitNames()
  28.  *
  29.  * Revision 3.2  1998/02/08 20:18:20  brianp
  30.  * removed unneeded headers
  31.  *
  32.  * Revision 3.1  1998/02/04 00:34:29  brianp
  33.  * fixed a few cast problems for Amiga StormC compiler
  34.  *
  35.  * Revision 3.0  1998/01/31 20:52:30  brianp
  36.  * initial rev
  37.  *
  38.  */
  39.  
  40.  
  41. #ifdef PC_HEADER
  42. #include "all.h"
  43. #else
  44. #include <assert.h>
  45. #include <stdio.h>
  46. #include "context.h"
  47. #include "feedback.h"
  48. #include "macros.h"
  49. #include "types.h"
  50. #endif
  51.  
  52.  
  53.  
  54. #define FB_3D           0x01
  55. #define FB_4D           0x02
  56. #define FB_INDEX        0x04
  57. #define FB_COLOR        0x08
  58. #define FB_TEXTURE      0X10
  59.  
  60.  
  61.  
  62. void
  63. gl_FeedbackBuffer( GLcontext *ctx, GLsizei size, GLenum type, GLfloat *buffer )
  64. {
  65.    if (ctx->RenderMode==GL_FEEDBACK || INSIDE_BEGIN_END(ctx)) {
  66.       gl_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
  67.       return;
  68.    }
  69.  
  70.    if (size<0) {
  71.       gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
  72.       return;
  73.    }
  74.    if (!buffer) {
  75.       gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
  76.       ctx->Feedback.BufferSize = 0;
  77.       return;
  78.    }
  79.  
  80.    switch (type) {
  81.       case GL_2D:
  82.      ctx->Feedback.Mask = 0;
  83.      ctx->Feedback.Type = type;
  84.      break;
  85.       case GL_3D:
  86.      ctx->Feedback.Mask = FB_3D;
  87.      ctx->Feedback.Type = type;
  88.      break;
  89.       case GL_3D_COLOR:
  90.      ctx->Feedback.Mask = FB_3D
  91.                | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX);
  92.      ctx->Feedback.Type = type;
  93.      break;
  94.       case GL_3D_COLOR_TEXTURE:
  95.      ctx->Feedback.Mask = FB_3D
  96.                | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
  97.                | FB_TEXTURE;
  98.      ctx->Feedback.Type = type;
  99.      break;
  100.       case GL_4D_COLOR_TEXTURE:
  101.      ctx->Feedback.Mask = FB_3D | FB_4D
  102.                | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
  103.                | FB_TEXTURE;
  104.      ctx->Feedback.Type = type;
  105.      break;
  106.       default:
  107.      ctx->Feedback.Mask = 0;
  108.      gl_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
  109.    }
  110.  
  111.    ctx->Feedback.BufferSize = size;
  112.    ctx->Feedback.Buffer = buffer;
  113.    ctx->Feedback.Count = 0;
  114. }
  115.  
  116.  
  117.  
  118. void gl_PassThrough( GLcontext *ctx, GLfloat token )
  119. {
  120.    if (INSIDE_BEGIN_END(ctx)) {
  121.       gl_error( ctx, GL_INVALID_OPERATION, "glPassThrough" );
  122.       return;
  123.    }
  124.  
  125.    if (ctx->RenderMode==GL_FEEDBACK) {
  126.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
  127.       FEEDBACK_TOKEN( ctx, token );
  128.    }
  129. }
  130.  
  131.  
  132.  
  133. /*
  134.  * Put a vertex into the feedback buffer.
  135.  */
  136. void gl_feedback_vertex( GLcontext *ctx,
  137.              GLfloat x, GLfloat y, GLfloat z, GLfloat w,
  138.              const GLfloat color[4], GLfloat index,
  139.              const GLfloat texcoord[4] )
  140. {
  141.    FEEDBACK_TOKEN( ctx, x );
  142.    FEEDBACK_TOKEN( ctx, y );
  143.    if (ctx->Feedback.Mask & FB_3D) {
  144.       FEEDBACK_TOKEN( ctx, z );
  145.    }
  146.    if (ctx->Feedback.Mask & FB_4D) {
  147.       FEEDBACK_TOKEN( ctx, w );
  148.    }
  149.    if (ctx->Feedback.Mask & FB_INDEX) {
  150.       FEEDBACK_TOKEN( ctx, index );
  151.    }
  152.    if (ctx->Feedback.Mask & FB_COLOR) {
  153.       FEEDBACK_TOKEN( ctx, color[0] );
  154.       FEEDBACK_TOKEN( ctx, color[1] );
  155.       FEEDBACK_TOKEN( ctx, color[2] );
  156.       FEEDBACK_TOKEN( ctx, color[3] );
  157.    }
  158.    if (ctx->Feedback.Mask & FB_TEXTURE) {
  159.       FEEDBACK_TOKEN( ctx, texcoord[0] );
  160.       FEEDBACK_TOKEN( ctx, texcoord[1] );
  161.       FEEDBACK_TOKEN( ctx, texcoord[2] );
  162.       FEEDBACK_TOKEN( ctx, texcoord[3] );
  163.    }
  164. }
  165.  
  166.  
  167.  
  168. /**********************************************************************/
  169. /*                              Selection                             */
  170. /**********************************************************************/
  171.  
  172.  
  173. /*
  174.  * NOTE: this function can't be put in a display list.
  175.  */
  176. void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer )
  177. {
  178.    if (INSIDE_BEGIN_END(ctx)) {
  179.       gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
  180.    }
  181.    if (ctx->RenderMode==GL_SELECT) {
  182.       gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
  183.    }
  184.    ctx->Select.Buffer = buffer;
  185.    ctx->Select.BufferSize = size;
  186.    ctx->Select.BufferCount = 0;
  187.  
  188.    ctx->Select.HitFlag = GL_FALSE;
  189.    ctx->Select.HitMinZ = 1.0;
  190.    ctx->Select.HitMaxZ = 0.0;
  191. }
  192.  
  193.  
  194. #define WRITE_RECORD( CTX, V )                                  \
  195.     if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \
  196.        CTX->Select.Buffer[CTX->Select.BufferCount] = (V);   \
  197.     }                                                       \
  198.     CTX->Select.BufferCount++;
  199.  
  200.  
  201.  
  202. void gl_update_hitflag( GLcontext *ctx, GLfloat z )
  203. {
  204.    ctx->Select.HitFlag = GL_TRUE;
  205.    if (z < ctx->Select.HitMinZ) {
  206.       ctx->Select.HitMinZ = z;
  207.    }
  208.    if (z > ctx->Select.HitMaxZ) {
  209.       ctx->Select.HitMaxZ = z;
  210.    }
  211. }
  212.  
  213.  
  214.  
  215. static void write_hit_record( GLcontext *ctx )
  216. {
  217.    GLuint i;
  218. #ifndef __STORM__
  219.    GLuint zmin, zmax, zscale = (~0u);
  220. #else
  221.    GLuint zmin, zmax, zscale = 0x7fffffff;
  222. #endif
  223.    /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
  224.    /* 2^32-1 and round to nearest unsigned integer. */
  225.  
  226.    assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
  227. #ifndef __STORM__
  228.    zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
  229.    zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
  230. #else
  231.    zmin = 2* (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
  232.    zmax = 2* (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
  233. #endif
  234.  
  235.    WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
  236.    WRITE_RECORD( ctx, zmin );
  237.    WRITE_RECORD( ctx, zmax );
  238.    for (i=0;i<ctx->Select.NameStackDepth;i++) {
  239.       WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
  240.    }
  241.  
  242.    ctx->Select.Hits++;
  243.    ctx->Select.HitFlag = GL_FALSE;
  244.    ctx->Select.HitMinZ = 1.0;
  245.    ctx->Select.HitMaxZ = -1.0;
  246. }
  247.  
  248.  
  249.  
  250. void gl_InitNames( GLcontext *ctx )
  251. {
  252.    if (INSIDE_BEGIN_END(ctx)) {
  253.       gl_error( ctx, GL_INVALID_OPERATION, "glInitNames" );
  254.    }
  255.    /* Record the hit before the HitFlag is wiped out again. */
  256.    if (ctx->RenderMode==GL_SELECT) {
  257.       if (ctx->Select.HitFlag) {
  258.      write_hit_record( ctx );
  259.       }
  260.    }
  261.    ctx->Select.NameStackDepth = 0;
  262.    ctx->Select.HitFlag = GL_FALSE;
  263.    ctx->Select.HitMinZ = 1.0;
  264.    ctx->Select.HitMaxZ = 0.0;
  265. }
  266.  
  267.  
  268.  
  269. void gl_LoadName( GLcontext *ctx, GLuint name )
  270. {
  271.    if (INSIDE_BEGIN_END(ctx)) {
  272.       gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
  273.       return;
  274.    }
  275.    if (ctx->RenderMode!=GL_SELECT) {
  276.       return;
  277.    }
  278.    if (ctx->Select.NameStackDepth==0) {
  279.       gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
  280.       return;
  281.    }
  282.    if (ctx->Select.HitFlag) {
  283.       write_hit_record( ctx );
  284.    }
  285.    if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  286.       ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
  287.    }
  288.    else {
  289.       ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
  290.    }
  291. }
  292.  
  293.  
  294. void gl_PushName( GLcontext *ctx, GLuint name )
  295. {
  296.    if (INSIDE_BEGIN_END(ctx)) {
  297.       gl_error( ctx, GL_INVALID_OPERATION, "glPushName" );
  298.       return;
  299.    }
  300.    if (ctx->RenderMode!=GL_SELECT) {
  301.       return;
  302.    }
  303.    if (ctx->Select.HitFlag) {
  304.       write_hit_record( ctx );
  305.    }
  306.    if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  307.       ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
  308.    }
  309.    else {
  310.       gl_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
  311.    }
  312. }
  313.  
  314.  
  315.  
  316. void gl_PopName( GLcontext *ctx )
  317. {
  318.    if (INSIDE_BEGIN_END(ctx)) {
  319.       gl_error( ctx, GL_INVALID_OPERATION, "glPopName" );
  320.       return;
  321.    }
  322.    if (ctx->RenderMode!=GL_SELECT) {
  323.       return;
  324.    }
  325.    if (ctx->Select.HitFlag) {
  326.       write_hit_record( ctx );
  327.    }
  328.    if (ctx->Select.NameStackDepth>0) {
  329.       ctx->Select.NameStackDepth--;
  330.    }
  331.    else {
  332.       gl_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
  333.    }
  334. }
  335.  
  336.  
  337.  
  338. /**********************************************************************/
  339. /*                           Render Mode                              */
  340. /**********************************************************************/
  341.  
  342.  
  343.  
  344. /*
  345.  * NOTE: this function can't be put in a display list.
  346.  */
  347. GLint gl_RenderMode( GLcontext *ctx, GLenum mode )
  348. {
  349.    GLint result;
  350.  
  351.    if (INSIDE_BEGIN_END(ctx)) {
  352.       gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  353.    }
  354.  
  355.    switch (ctx->RenderMode) {
  356.       case GL_RENDER:
  357.      result = 0;
  358.      break;
  359.       case GL_SELECT:
  360.      if (ctx->Select.HitFlag) {
  361.         write_hit_record( ctx );
  362.      }
  363.      if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
  364.         /* overflow */
  365. #ifdef DEBUG
  366.         gl_warning(ctx, "Feedback buffer overflow");
  367. #endif
  368.         result = -1;
  369.      }
  370.      else {
  371.         result = ctx->Select.Hits;
  372.      }
  373.      ctx->Select.BufferCount = 0;
  374.      ctx->Select.Hits = 0;
  375.      ctx->Select.NameStackDepth = 0;
  376.      break;
  377.       case GL_FEEDBACK:
  378.      if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
  379.         /* overflow */
  380.         result = -1;
  381.      }
  382.      else {
  383.         result = ctx->Feedback.Count;
  384.      }
  385.      ctx->Feedback.Count = 0;
  386.      break;
  387.       default:
  388.      gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  389.      return 0;
  390.    }
  391.  
  392.    switch (mode) {
  393.       case GL_RENDER:
  394.      break;
  395.       case GL_SELECT:
  396.      if (ctx->Select.BufferSize==0) {
  397.         /* haven't called glSelectBuffer yet */
  398.         gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  399.      }
  400.      break;
  401.       case GL_FEEDBACK:
  402.      if (ctx->Feedback.BufferSize==0) {
  403.         /* haven't called glFeedbackBuffer yet */
  404.         gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  405.      }
  406.      break;
  407.       default:
  408.      gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  409.      return 0;
  410.    }
  411.  
  412.    ctx->RenderMode = mode;
  413.    ctx->NewState |= NEW_ALL;
  414.  
  415.    return result;
  416. }
  417.  
  418.